package com.android.support.lib.universal.view.tv;

import android.animation.Animator;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;

import com.android.support.lib.universal.R;
import com.android.support.lib.universal.view.tv.bridge.BaseEffectBridge;
import com.android.support.lib.universal.view.tv.bridge.EffectNoDrawBridge;
import com.android.support.lib.universal.view.tv.bridge.OpenEffectBridge;

/**
 * 布局:每个布局文件(如多个Fragment布局)都要单独使用一个MainUpView。尽量不要多个布局公用一个。
 * <com.android.support.lib.universal.view.tv.MainUpView
 * android:id="@+id/mainupview"
 * android:layout_width="wrap_content"
 * android:layout_height="wrap_content"
 * android:visibility="gone" />
 * 初始化：
 * mainUpView = (MainUpView) view.findViewById(R.id.mainupview);
 * mainUpView.initMainUpView(R.mipmap.mainupview_gridview,null);
 * <p>
 * 全局聚焦事件
 * <p>
 * //        view.getViewTreeObserver().addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
 * //            @Override
 * //            public void onGlobalFocusChanged(final View oldFocus, final View newFocus) {
 * //                if (newFocus != null){
 * //                    mainUpView.setFocusView(newFocus,scale);
 * //                }
 * //            }
 * //        });
 * <p>
 * 一：MainUpView是一个在最上层的移动边框.必须放在最顶层的父容器布局里。
 * 二：<!-- android:clipChildren="false" android:clipToPadding="false" 在最顶层容器设置。不要忘记了，不然移动的边框无法显示出来 -->
 * 三：切记！不要出现与mainpuView有关的位置属性。如：android:layout_alignParentBottom="true"，否则出现焦点位置错乱。
 * 四：ImageView尽量设置背景android:background而不能设置src,防止边框大小对不上
 * 五：MainUpView放大之后的大小，不能超过父容器的大小。不然边框对不上。如子View不能超过ViewPager的大小
 * <p/>
 * 边框图片相关API:边框图片会显示在最上面
 * <li>{@link #setUpRectResource}
 * <li>{@link #setUpRectDrawable}
 * <li>{@link #getUpRectDrawable}
 * <li>{@link #setDrawUpRectPadding(int)} 用于调整边框图片边距.
 * <li>{@link #setDrawUpRectPadding(Rect)} 用于调整边框图片边距.
 * <p/>
 * 阴影图片相关API: 阴影图片在边框图片的下面显示。但是会覆盖在内容之上。
 * <li>{@link #setShadowResource}
 * <li>{@link #setShadowDrawable}
 * <li>{@link #getShadowDrawable}
 * <li>{@link #setDrawShadowPadding(int)} 用于调整阴影图片边距
 * <li>{@link #setDrawShadowRectPadding(Rect)} 用于调整阴影图片边距
 * <p/>
 * Effcet相关API:
 * <li>{@link #setEffectBridge} 你可以设置自己的放大，边框移动的动画效果.
 * <li>{@link #getEffectBridge}
 * <p/>
 * 焦点View相关API:
 * <li>{@link #setFocusView(View, float, float)}
 * <li>{@link #setFocusView(View, float)}
 * <li>{@link #setUnFocusView}
 * </ul>
 * <p/>
 * <p/>
 */
public class MainUpView extends FrameLayout {

    private static final String TAG = "MainUpView";
    private static final float DEFUALT_SCALE = 1.0f;

    private BaseEffectBridge mEffectBridge;

    public MainUpView(Context context) {
        super(context, null, 0);
        init(context, null);
    }

    private View oldView;//记录旧焦点
    private OnFocusChangeListener oldOnFocusChangeListener;//记录旧焦点的聚焦事件


    /**
     * 手动添加，不在XML添加的话.
     */
    public void attach2Window(Activity activity) {
        ViewGroup rootView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        rootView.addView(this, layoutParams);
        rootView.setClipChildren(false);
        rootView.setClipToPadding(false);
    }

    public MainUpView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        init(context, attrs);
    }

    public MainUpView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        setWillNotDraw(false);
        initEffectBridge();
        if (isInEditMode()) {
            return;
        }
        // 初始化.
        if (attrs != null) {
            TypedArray tArray = context.obtainStyledAttributes(attrs, R.styleable.MainUpView);// 获取配置属性
            Drawable drawableUpRect = tArray.getDrawable(R.styleable.MainUpView_upImageRes); // 顶层图片.
            Drawable drawableShadow = tArray.getDrawable(R.styleable.MainUpView_shadowImageRes); // 阴影图片.
            setUpRectDrawable(drawableUpRect);
            setShadowDrawable(drawableShadow);
            tArray.recycle();
        }
    }

    private void initEffectBridge() {
        BaseEffectBridge baseEffectBridge = new OpenEffectBridge();
        baseEffectBridge.onInitBridge(this);
        baseEffectBridge.setMainUpView(this);
        setEffectBridge(baseEffectBridge);
    }

    /**
     * 设置最上层的图片资源ID.
     */
    public void setUpRectResource(int resId) {
        if (mEffectBridge != null)
            mEffectBridge.setUpRectResource(resId);
    }

    /**
     * 设置最上层的边框.
     */
    public void setUpRectDrawable(Drawable upRectDrawable) {
        if (mEffectBridge != null)
            mEffectBridge.setUpRectDrawable(upRectDrawable);
    }

    /**
     * 获取最上层图片.
     */
    public Drawable getUpRectDrawable() {
        if (mEffectBridge != null) {
            return mEffectBridge.getUpRectDrawable();
        }
        return null;
    }

    /**
     * 根据图片边框 自行 填写 相差的边距. <br>
     * 比如 res/drawble/white_light_10.9.png的图片，边距就差很多.
     *
     * @param size 负数边框减小，正数反之(阴影边框一样的).
     */
    public void setDrawUpRectPadding(int size) {
        setDrawUpRectPadding(new Rect(size, size, size, size));
    }

    /**
     * 根据图片边框 自行 填写 相差的边距. <br>
     * 比如 res/drawble/white_light_10.9.png的图片，边距就差很多.
     */
    public void setDrawUpRectPadding(Rect rect) {
        if (mEffectBridge != null) {
            mEffectBridge.setDrawUpRectPadding(rect);
            invalidate();
        }
    }

    public void setDrawUpRectPadding(RectF rect) {
        if (mEffectBridge != null) {
            mEffectBridge.setDrawUpRectPadding(rect);
            invalidate();
        }
    }

    /**
     * 获取最上层图片 间距矩形(Rect).
     */
    public Rect getDrawUpRect() {
        if (mEffectBridge != null) {
            RectF rectf = mEffectBridge.getDrawUpRect();
            int left = (int) Math.rint(rectf.left);
            int right = (int) Math.rint(rectf.right);
            int bottom = (int) Math.rint(rectf.bottom);
            int top = (int) Math.rint(rectf.top);
            return new Rect(left, top, right, bottom);
        }
        return null;
    }

    public RectF getDrawUpRectF() {
        if (mEffectBridge != null) {
            return mEffectBridge.getDrawUpRect();
        }
        return null;
    }

    /**
     * 设置阴影图片资源ID.
     */
    public void setShadowResource(int resId) {
        if (mEffectBridge != null) {
            this.mEffectBridge.setShadowResource(resId);
            invalidate();
        }
    }

    /**
     * 当图片边框不自带阴影的话，可以自行设置阴影图片. 设置阴影.
     */
    public void setShadowDrawable(Drawable shadowDrawable) {
        if (mEffectBridge != null) {
            this.mEffectBridge.setShadowDrawable(shadowDrawable);
            invalidate();
        }
    }

    /**
     * 获取阴影图片.
     */
    public Drawable getShadowDrawable() {
        if (mEffectBridge != null) {
            return this.mEffectBridge.getShadowDrawable();
        }
        return null;
    }

    /**
     * 根据阴影图片边框 自行 填写 相差的边距. <br>
     * 比如 res/drawble/white_shadow.9.png的图片，边距就差很多.
     */
    public void setDrawShadowPadding(int size) {
        setDrawShadowRectPadding(new Rect(size, size, size, size));
    }

    /**
     * 根据阴影图片边框 自行 填写 相差的边距. <br>
     * 比如 res/drawble/white_shadow.9.png的图片，边距就差很多.
     */
    public void setDrawShadowRectPadding(Rect rect) {
        if (mEffectBridge != null) {
            mEffectBridge.setDrawShadowRectPadding(rect);
            invalidate();
        }
    }

    /**
     * 获取阴影图片边距.
     */
    public Rect getDrawShadowRect() {
        if (mEffectBridge != null) {
            RectF rectf = mEffectBridge.getDrawShadowRect();
            int left = (int) Math.rint(rectf.left);
            int right = (int) Math.rint(rectf.right);
            int bottom = (int) Math.rint(rectf.bottom);
            int top = (int) Math.rint(rectf.top);
            return new Rect(left, top, right, bottom);
        }
        return null;
    }

    /**
     * 获取阴影图片边距.
     */
    public RectF getDrawShadowRectF() {
        if (mEffectBridge != null) {
            return mEffectBridge.getDrawShadowRect();
        }
        return null;
    }

    /**
     * 初始化，切记一定要调用该方法
     *
     * @param mainUpView 设置移动边框的图片
     * @param rectF      用于调整边框图片边距(边框内补丁)
     */
    public void initMainUpView(int mainUpView, RectF rectF) {
        setEffectBridge(new EffectNoDrawBridge());
        //设置在setEffectBridge()之后，不然无效果。
        setUpRectResource(mainUpView);// 设置移动边框的图片
        if (rectF == null) {
            setDrawUpRectPadding(new RectF(0, 0, 0, 0));//用于调整边框图片边距
        } else {
            setDrawUpRectPadding(rectF);
        }
        EffectNoDrawBridge bridget = (EffectNoDrawBridge) getEffectBridge();
        bridget.setTranDurAnimTime(150);
        //mianupview添加动画监听
        ((EffectNoDrawBridge) getEffectBridge()).setOnAnimatorListener(new OpenEffectBridge.NewAnimatorListener() {
            @Override
            public void onAnimationStart(OpenEffectBridge bridge, View view, Animator animation) {
                //Log.e("test","动画开始:\t"+(oldView == null));
                //动画开始不要隐藏边框，不然没有边框移动的动画效果。
            }

            @Override
            public void onAnimationEnd(OpenEffectBridge bridge, View view, Animator animation) {
                //Log.e("test","动画结束:\t"+(oldView == null));
                if (oldView == null) {
                    setVisibility(View.GONE);//防止因为动画，mianupView未能隐藏
                }
            }
        });
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            removeMessages(msg.what);
            if (oldView == null) {//失去焦点时，而又没有新的聚焦。则隐藏(解决了鼠标点击时的焦点错误)
                setVisibility(View.GONE);
            }
        }
    };

    /**
     * 移动到 view的位置，并且放大 view.
     *
     * @param view
     * @param scale 放大比例 可以设置为1.2f, 1.1f或者其它
     */
    public void setFocusView(View view, final float scale) {
        //Log.e("test", "聚焦:\t" + (view != oldView) + "\tID:\t" + view.getId() + "\t空:\t" + (view == null));
        if (view != oldView) {
            //Log.e("test","是否具有聚焦能力:\t"+view.isFocusable()+"\t是否聚焦:\t"+view.isFocused());
            if (view.isFocusable() && view.isFocused()) {
                view.requestFocus();
                view.requestFocusFromTouch();
            }
            view.bringToFront();//聚焦视图置前(显示在其他View的前面)
            bringToFront();//边框再置前(显示在view的前面)
            setFocusView(view, scale, scale);//mainUpView就算是隐藏状态，聚焦时也会自动显示。所以不需刻意setVisibility(View.VISIBLE);
            //保存原有的聚焦事件,失去焦点时要恢复原有聚焦事件
            oldOnFocusChangeListener = view.getOnFocusChangeListener();
            //设置新的聚焦监听事件
            view.setOnFocusChangeListener(new OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (!hasFocus) {
                        setUnFocusView(v);
                        handler.sendEmptyMessageDelayed(0, 30);
                    }
                    //集成原有聚焦事件，防止原有聚焦事件失灵。
                    if(oldOnFocusChangeListener!=null){
                        oldOnFocusChangeListener.onFocusChange(v, hasFocus);
                    }
                }
            });

            setUnFocusView(oldView);
            this.oldView = view;
        }
    }

    /**
     * 移动到 view的位置，并且放大 view.
     *
     * @param view
     * @param scaleX X放大比例
     * @param scaleY Y放大比例
     */
    public void setFocusView(View view, float scaleX, float scaleY) {
        if (this.mEffectBridge != null)
            this.mEffectBridge.onFocusView(view, scaleX, scaleY);
    }

    /**
     * 设置无焦点子控件还原.(默认为1.0F)
     *
     * @param view 老焦点View.
     */
    public void setUnFocusView(View view) {
        if (view != null) {
            setUnFocusView(view, DEFUALT_SCALE, DEFUALT_SCALE);
        }
        if (oldView != null) {
            //恢复原有的聚焦事件
            oldView.setOnFocusChangeListener(oldOnFocusChangeListener);
            oldView = null;
        }
    }

    /**
     * 老焦点VIEW处理.
     *
     * @param view
     * @param scaleX X缩放比例
     * @param scaleY Y缩放比例
     */
    public void setUnFocusView(View view, float scaleX, float scaleY) {
        if (this.mEffectBridge != null)
            this.mEffectBridge.onOldFocusView(view, scaleX, scaleY);
    }

    /**
     * 设置EffectBridge.
     * BaseEffectBridge 处理了边框的移动，边框的绘制.
     * 具体查看 BaseEffectBridge 类.
     */
    public void setEffectBridge(BaseEffectBridge effectBridge) {
        this.mEffectBridge = effectBridge;
        if (this.mEffectBridge != null) {
            this.mEffectBridge.onInitBridge(this);
            this.mEffectBridge.setMainUpView(this);
            invalidate();
        }
    }

    public BaseEffectBridge getEffectBridge() {
        return this.mEffectBridge;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (this.mEffectBridge != null) {
            if (this.mEffectBridge.onDrawMainUpView(canvas)) {
                return;
            }
        }
        super.onDraw(canvas);
    }

}
